﻿using GKQC.Common;
using GKQC.DbHelper.Dao;
using GKQC.DbHelper.DbModels;
using GKQC.DbHelper.ViewModels;
using SqlSugar;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace GKQC.DbHelper.Services
{
    public class RndService
    {
        AllDbContext dbContext;

        public RndService(AllDbContext dbContext)
        {
            this.dbContext = dbContext;
        }

        public List<RndDtlModel> GetDtls(long headId)
        {
            List <RndDtlModel> dtls =  dbContext.QcDb.Queryable<RndDtlModel>().Where(d => d.HeadId == headId)
                .OrderBy(d => d.SNo, OrderByType.Asc)
                .ToList();
            if(dtls != null)
            {
                foreach(RndDtlModel d in dtls)
                {
                    d.ElectricViewModels = new List<ElectricViewModel>();
                    d.SizeViewModels = new List<SizeViewModel>();
                }
            }
            return dtls;
        }

        public List<RndDataModel> GetDatas(long headId, int sNo)
        {
            return dbContext.QcDb.Queryable<RndDataModel>()
                .Where(d => d.HeadId == headId && d.SNo == sNo)
                .ToList();
        }
        public List<RndDataModel> GetDatas(long headId)
        {
            return dbContext.QcDb.Queryable<RndDataModel>()
                .Where(d => d.HeadId == headId)
                .ToList();
        }

        public List<RndDataModel> GetDatas(RndHeadModel headModel, RndDtlModel dtl)
        {
            if (headModel == null || dtl == null || headModel.Id <= 0 || dtl.SNo <= 0) return null;
            List<RndDataModel> datas = GetDatas(headModel.Id, dtl.SNo);
            ViewModelTrans<RndDataModel>.DataToView(dtl.SNo, datas, dtl.ElectricViewModels, dtl.SizeViewModels);
            return datas;
        }

        public RndHeadModel GetHeadByLotNo(string lotNo)
        {
            var heads = dbContext.QcDb.Queryable<RndHeadModel>().Where(o => o.LotNo == lotNo);
            if (heads != null && heads.Count() > 0)
                return heads.First();
            else
                return null;
        }

        public RndHeadModel GetHeadById(long id)
        {
            var heads = dbContext.QcDb.Queryable<RndHeadModel>().Where(o => o.Id == id);
            if (heads != null && heads.Count() > 0)
                return heads.First();
            else
                return null;
        }

        public List<RndHeadModel> GetHeads(int count)
        {
            return dbContext.QcDb.Queryable<RndHeadModel>()
                .OrderBy(o => o.TestDate, OrderByType.Desc)
                .Take(count).ToList();
        }

        public RndHeadModel GetHead(string pn, string customerPn)
        {
            return dbContext.QcDb.Queryable<RndHeadModel>()
                .Where(t=>t.Pn==pn && t.CustomerPn == customerPn)
                .OrderBy(o => o.TestDate, OrderByType.Desc)
                .ToList().FirstOrDefault();
        }

        public RndHeadModel GetHead(string series, double cap,double voltage,double D, double L )
        {
            if (string.IsNullOrWhiteSpace(series)) return null;

            return dbContext.QcDb.Queryable<RndHeadModel>()
                .Where(t => t.Series == series && t.Cap == cap && t.Voltage == voltage
                    && t.D == D && t.L == L)
                .OrderBy(o => o.TestDate, OrderByType.Desc)
                .ToList().FirstOrDefault();
        }

        public int Save(RndHeadModel headModel)
        {
            int i = 0;

            bool isNew = false;
            try
            {
                dbContext.QcDb.Ado.BeginTran();
                if (headModel.Id <= 0)
                {
                    if (!dbContext.QcDb.Insertable(headModel).ExecuteCommandIdentityIntoEntity())
                        throw new Exception("U0001: 新增保存出錯");

                    isNew = true;
                }
                if(!isNew)
                    dbContext.QcDb.Deleteable<RndDataModel>()
                        .Where(o => o.HeadId == headModel.Id)
                        .ExecuteCommand();
                if (isNew) headModel.Dtls.ForEach(d => d.HeadId = headModel.Id);
                List<RndDataModel> datas = new List<RndDataModel>();
                if (headModel.Dtls.Count > 0)
                {
                    foreach (RndDtlModel dtl in headModel.Dtls)
                    {
                        dtl.HeadId = headModel.Id;
                        List<RndDataModel> dtl_datas = new List<RndDataModel>();
                        if (dtl.ElectricViewModels != null && dtl.ElectricViewModels.Count > 0)
                        {
                            dtl_datas.AddRange(ViewModelTrans<RndDataModel>.ElectricViewToData(headModel.Id, dtl.SNo, dtl.ElectricViewModels));
                        }
                        if (dtl.SizeViewModels != null && dtl.SizeViewModels.Count > 0)
                        {
                            dtl_datas.AddRange(ViewModelTrans<RndDataModel>.SizeViewToData(headModel.Id, dtl.SNo, dtl.SizeViewModels));
                        }

                        dtl.Datas = dtl_datas;
                        datas.AddRange(dtl_datas);
                    }

                    var overLengths = datas.Where(d => d.Value > 9999999999);
                    if (overLengths != null && overLengths.Count() > 0)
                        overLengths.ToList().ForEach(o => o.Value = 9999999999);
                    var overLengths2 = datas.Where(d => d.Value < -9999999999);
                    if (overLengths2 != null && overLengths2.Count() > 0)
                        overLengths2.ToList().ForEach(o => o.Value = -9999999999);
                }

                List<RndDtlModel> dtls = headModel.Dtls.Where(d => d.Id > 0).ToList();
                if(dtls != null && dtls.Count >0)
                dbContext.QcDb.Updateable(dtls)
                    .ExecuteCommand();
                dtls = headModel.Dtls.Where(d => d.Id <= 0).ToList();
                if (dtls != null && dtls.Count > 0)
                    dbContext.QcDb.Insertable(dtls)
                    .ExecuteCommand();
                if(datas.Count > 0)
                    dbContext.QcDb.Insertable(datas)
                    .ExecuteCommand();
                if (!isNew)
                    i = dbContext.QcDb.Updateable(headModel)
                        .ExecuteCommand();
                else
                    i = 1;

                dbContext.QcDb.Ado.CommitTran();
            }
            catch (Exception ex)
            {
                dbContext.QcDb.Ado.RollbackTran();
                Logger.LogError(ex);
                throw ex;
            }
            return i;
        }

        /// <summary>
        /// 複製，不包含檢測數據
        /// </summary>
        /// <param name="RndHeadModel"></param>
        /// <returns></returns>
        public RndHeadModel Clone(RndHeadModel RndHeadModel)
        {
            RndHeadModel newModel;
            if (RndHeadModel == null)
                newModel = new RndHeadModel();
            else newModel = ClassClone<RndHeadModel, RndHeadModel>.Clone(RndHeadModel);
            newModel.Id = 0;
            newModel.ModiDate = null;
            newModel.ModiUser = string.Empty;
            if (newModel.Dtls != null && newModel.Dtls.Count > 0)
            {
                newModel.Dtls = new List<RndDtlModel>();
            }

            return newModel;
        }

        /// <summary>
        /// 審核
        /// </summary>
        /// <param name="ortList"></param>
        /// <returns></returns>
        public int Approve(List<RndHeadModel> ortList)
        {
            int i = 0;
            i = dbContext.QcDb.Updateable(ortList)
                .UpdateColumns(it => new { it.ApproveUser, it.ApproveDate })
                .ExecuteCommand();
            return i;
        }


        /// <summary>
        /// 反審核
        /// </summary>
        /// <param name="headList"></param>
        /// <returns></returns>
        public int UnApprove(List<RndHeadModel> headList)
        {
            int i = 0;
            if (headList != null && headList.Count > 0)
            {
                i = dbContext.QcDb.Updateable(headList)
                    .UpdateColumns(it => new { it.ApproveUser, it.ApproveDate })
                    .ExecuteCommand();
            }
            return i;
        }

        /// <summary>
        /// 刪除
        /// </summary>
        /// <param name="ortList"></param>
        /// <returns></returns>
        public int Delete(List<RndHeadModel> ortList)
        {
            int i = 0;
            try
            {
                dbContext.QcDb.Ado.BeginTran();
                dbContext.QcDb.Deleteable<RndDataModel>()
                    .In(it => it.HeadId, ortList.Select(o => o.Id).ToArray())
                    .ExecuteCommand();
                dbContext.QcDb.Deleteable<RndDtlModel>()
                    .In(it => it.HeadId, ortList.Select(o => o.Id).ToArray())
                    .ExecuteCommand();
                i = dbContext.QcDb.Deleteable(ortList)
                    .ExecuteCommand();
                dbContext.QcDb.Ado.CommitTran();
            }
            catch(Exception ex)
            {
                dbContext.QcDb.Ado.RollbackTran();
                Logger.LogError(ex);
                throw ex;
            }
            return i;
        }

        public List<RndHeadModel> Query(RndFilter filter)
        {
            if (filter == null) return GetHeads(100);

            return dbContext.QcDb.Queryable<RndHeadModel>()
                .WhereIF(!string.IsNullOrWhiteSpace(filter.LotNo), t => t.LotNo == filter.LotNo)
                .WhereIF(!string.IsNullOrWhiteSpace(filter.Customer), t => t.Customer == filter.Customer)
                .WhereIF(!string.IsNullOrWhiteSpace(filter.CustomerPn), t => t.CustomerPn == filter.CustomerPn)
                .WhereIF(!string.IsNullOrWhiteSpace(filter.Pn), t => t.Pn == filter.Pn)
                .WhereIF(!string.IsNullOrWhiteSpace(filter.Series), t => t.Series == filter.Series)
                .WhereIF(filter.Cap >0, t => t.Cap == filter.Cap)
                .WhereIF(filter.Voltage > 0, t => t.Voltage == filter.Voltage)
                .WhereIF(filter.D>0, t => t.D == filter.D)
                .WhereIF(filter.L>0, t => t.L == filter.L)
                .WhereIF(filter.IsTestDate, t => t.TestDate >= filter.StartTestDate.Date)
                .WhereIF(filter.IsTestDate, t => t.TestDate < filter.EndTestDate.AddDays(1).Date)
                .WhereIF(filter.ReportId > 0, t => t.ReportId == filter.ReportId)
                .WhereIF(filter.IsApprove && !filter.IsUnApprove, t => !SqlFunc.IsNullOrEmpty(t.ApproveUser))
                .WhereIF(!filter.IsApprove && filter.IsUnApprove, t => SqlFunc.IsNullOrEmpty(t.ApproveUser))
                .WhereIF(filter.IsModiDate, t => t.ModiDate >= filter.StartModiDate.Date)
                .WhereIF(filter.IsModiDate, t => t.ModiDate < filter.EndModiDate.AddDays(1).Date)
                .OrderBy(t => t.TestDate, OrderByType.Desc)
                .Take(filter.RowCount).ToList();

        }

        public void GenStandard(RndHeadModel head,RndDtlModel dtl)
        {
            try
            {
                if (dtl.Condiction == "高溫")
                {
                    head.Standard.LcMax = head.LcMaxHigh;
                }
                else if (dtl.Condiction == "耐衝擊")
                {
                    head.Standard.LcMax = head.LcMaxShock;
                }
                else
                {
                    head.Standard.LcMax = head.LcMax;
                }

                if (dtl.Condiction == "耐衝擊")
                    head.Standard.DfMax = head.DfMaxShock;
                else
                    head.Standard.DfMax = head.DfMax;

                head.Standard.CapMax = head.Cap * (1 + head.CapMax/100);
                head.Standard.CapMin = head.Cap * (1 + head.CapMin/100);
                head.Standard.ZMax = head.ZMax;
                head.Standard.Z2Max = head.Z2Max;
                head.Standard.EsrMax = head.EsrMax;
                head.Standard.DMax = head.DMax;
                head.Standard.LMax = head.LMax;

                if (head.Standard.ZMax == 0 && head.Standard.EsrMax > 0) head.Standard.ZMax = head.Standard.EsrMax;
                if (head.Standard.Z2Max == 0 && head.Standard.ZMax > 0) head.Standard.Z2Max = head.Standard.ZMax;
                if (head.Standard.EsrMax == 0 && head.Standard.ZMax > 0) head.Standard.EsrMax = head.Standard.ZMax;
            }
            catch (Exception ex)
            {
                Logger.LogError(ex);
                throw ex;
            }
        }
    }
}
